package com.apes.framework.plugin.esb.processor;

import com.apes.framework.plugin.esb.api.Request;
import com.apes.framework.util.Tools;
import com.apes.oap.response.OapResponse;
import org.springframework.dao.PessimisticLockingFailureException;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;

/**
 * 功能：action处理器类
 *
 * @author xul
 * @create 2017-12-04 13:41
 */
public class ActionProcessor<T extends Request, R> extends AbstractChainProcessor<T, R> {
    private Object target;
    private Method method;
    private String parameterTypes = null;

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public String getParameterTypes() {
        if (parameterTypes != null) return parameterTypes;
        Class<?>[] parameters = method.getParameterTypes();
        if (parameters == null || parameters.length == 0) return "void";
        parameterTypes = Tools.getParameterTypes(parameters);
        return parameterTypes;
    }

    @Override
    protected R doProcess(T data) {
        Object result;
        Assert.isTrue(!(method.getParameterTypes().length > 1), target.getClass() + "." + getMethod().getName() + ": 方法输入参数不合法。");
        try {
            if (method.getParameterTypes().length == 1) {
                result = ReflectionUtils.invokeMethod(method, target, data);
            } else {
                result = ReflectionUtils.invokeMethod(method, target);
            }
        } catch (Throwable e) {
            if (e instanceof ObjectOptimisticLockingFailureException) { //乐观锁
                throw e;
            } else if (e instanceof PessimisticLockingFailureException) { //悲观锁
                throw e;
            } else {
                if (e instanceof NullPointerException || e instanceof ArrayIndexOutOfBoundsException) {
                    throw new RuntimeException(e.getClass().getName() + " ：" + Tools.getFirstStackTrace(e));
                }
                throw new RuntimeException(e);
            }
        }
        if (result instanceof OapResponse) {
            OapResponse response = ((OapResponse) result);
            String code = response.getHeader().getCode();
            code = code != null ? code : "success";
            if (!code.equals("success")) {
                throw new RuntimeException(response.getBody().toString());
            }
            result = response.getBody();
        }
        return (R) result;
    }
}
